﻿///////////////////////////////////////////////////////
//
// XDesigner.ORM 
//
// autohr : yuans
//
// date: 2011-2-23
//
// email  : yyf9989@hotmail.com
// 
//
///////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections ;
using XDesigner.ORM.DOM;
using System.IO;
using System.Reflection;

namespace XDesigner.ORM
{
    public class ORMCodeGenerator
    {
        public static void GenareteCode2(string fileName, string outputFilename)
        {
            using (StreamReader reader = new StreamReader(fileName, true))
            {
                using (StreamWriter writer = new StreamWriter(outputFilename, false, Encoding.Default))
                {
                    string strLine = reader.ReadLine();
                    while (strLine != null)
                    {
                        strLine = strLine.Replace("\\", "\\\\");
                        strLine = strLine.Replace("\"", "\\\"");
                        writer.WriteLine("writer.WriteLine(\"" + strLine + "\");");

                        strLine = reader.ReadLine();
                    }
                }
            }
        }

        private static string ToStringValueCode(string v)
        {
            if (v == null)
            {
                return "null";
            }
            else if (v.Length == 0)
            {
                return "string.Empty";
            }
            else
            {
                StringBuilder str = new StringBuilder();
                str.Append("\"");
                foreach (char c in v)
                {
                    if (c == '\r')
                        str.Append(@"\r");
                    else if (c == '\n')
                        str.Append(@"\n");
                    else if (c == '\"')
                        str.Append("\\");
                    else
                        str.Append(c);
                }
                str.Append("\"");
                return str.ToString();
            }
        }

        internal static string ToTypeNameCode(Type type, bool fullName)
        {
            string result = null;
            if (type.IsGenericType)
            {
                Type baseType = type.GetGenericTypeDefinition();
                Type[] aTypes = type.GetGenericArguments();
                StringBuilder str = new StringBuilder();
                foreach (Type t in aTypes)
                {
                    if (str.Length > 0)
                    {
                        str.Append(",");
                    }
                    str.Append(ToTypeNameCode(t, true));
                }//foreach
                string strFullName = baseType.FullName;
                int index = strFullName.IndexOf("`");
                if (index > 0)
                {
                    strFullName = strFullName.Substring(0, index);
                    result = strFullName + "<" + str.ToString() + ">";
                }
                else
                {
                    result = type.FullName;
                }
            }
            else if (type.IsArray)
            {
                Type itemType = type.GetElementType();
                result = ToTypeNameCode(itemType, fullName) + "[]";
            }
            else
            {
                if (fullName)
                {
                    result = type.FullName;
                }
                else
                {
                    result = type.Name;
                }
            }
            result = result.Replace("+", ".");
            return result;
        }

        private static void WriteCommandCode(
            TextWriter writer,
            ORMDBCommand cmd,
            string variableName,
            string instanceName,
            string currentPropertyName)
        {
            //writer.WriteLine("        object parameterValue = null;");
            writer.WriteLine("        " + variableName + ".CommandText = " + ToStringValueCode(cmd.CommandText) + ";");
            foreach (ORMDBParameter p in cmd.Parameters)
            {
                ORMPropertyInfo prop = (ORMPropertyInfo)p.Value;
                ORMRelationInfo relation = prop.Relation;
                string valueCode = null;
                if (relation != null)
                {
                    if (relation.ChildProperty == null)
                    {
                        throw new NotSupportedException(
                            string.Format(ORMStrings.NotSupportedDelayLoad_Name, prop.Name));
                    }

                    if (string.Compare(prop.Name, currentPropertyName, true) == 0)
                    {
                        valueCode = "this.DBValue_" + prop.Name;
                    }
                    else
                    {
                        if (relation.RuntimeStyle == ORMRelationStyle.OneToOne)
                        {
                            //writer.WriteLine("      if( " + instanceName + "." + prop.Name + " == null )");
                            //writer.WriteLine("           parameterValue = null;");
                            //writer.WriteLine("      else");
                            //writer.WriteLine("           parameterValue = " + instanceName + "." + prop.Name + "." + relation.ChildProperty.Name + " ;");

                            valueCode = instanceName + "." + prop.Name
                                + " == null ? (object)DBNull.Value : ( object )" + instanceName + "."
                                + prop.Name + "." + relation.ChildProperty.Name;

                        }
                        else if (relation.RuntimeStyle == ORMRelationStyle.OneToManyWithKeyList)
                        {
                            valueCode = instanceName + "." + prop.Name
                                + " == null ? ( object) DBNull.Value : ( object )base.GetKeyValueList( context , " + instanceName + "."
                                + prop.Name + ", \"" + relation.ChildProperty.Name + "\")";
                        }
                    }
                }
                else
                {
                    valueCode = instanceName + "." + prop.Name;
                    if (Util.HasContent(prop.Format))
                    {
                        if (Util.IsImplementInterfaceType(prop.PropertyType, typeof(IFormattable)))
                        {
                            valueCode = "((System.IFormattable) " + instanceName + "." + prop.Name + " ).ToString(" + ToStringValueCode(prop.Format) + ", null )";
                        }
                    }
                }
                writer.WriteLine("        " + variableName + ".Parameters.AddParameter( "
                    + ToStringValueCode(p.ParameterName) + " , " + valueCode + " );");
            }//foreach
        }

        public static string GenerateORMHelperClassesCode(
            ORMContext context,
            ORMTypeInfo[] types,
            string nameSpace,
            List<Type> referenceTypes)
        {
            StringWriter writer = new StringWriter();
            writer.WriteLine("using System;");
            writer.WriteLine("using System.Data;");
            writer.WriteLine("using System.Collections.Generic;");
            writer.WriteLine("using System.Collections;");
            writer.WriteLine("using XDesigner.ORM;");
            writer.WriteLine("namespace " + nameSpace);
            writer.WriteLine("{");
            foreach (ORMTypeInfo type in types)
            {
                writer.WriteLine("");
                writer.WriteLine("");
                writer.WriteLine(GenerateORMHelperClassCode(context, type, referenceTypes));
            }
            writer.WriteLine("}");
            return writer.ToString();
        }


        private class PropertyGenerateInfo
        {
            public bool GenreateTempValue = false;
            public string ConvertFunctionName = null;
        }


        public static string GenerateORMHelperClassCode(ORMContext context, ORMTypeInfo type, List<Type> referenceTypes)
        {
            ReflectionORMTypeMappingHelper helper = new ReflectionORMTypeMappingHelper(type);

            if (referenceTypes != null
                && referenceTypes.Contains(type.InstanceType) == false)
            {
                referenceTypes.Add(type.InstanceType);
            }
            string fullTypeName = ToTypeNameCode(type.InstanceType, true);
            string typeName = ToTypeNameCode(type.InstanceType, false);

            Dictionary<ORMPropertyInfo, PropertyGenerateInfo> propertyInfos = new Dictionary<ORMPropertyInfo, PropertyGenerateInfo>();
            foreach (ORMPropertyInfo property in type.Properties)
            {
                PropertyGenerateInfo info = new PropertyGenerateInfo();
                propertyInfos[property] = info;
                info.GenreateTempValue = property.GenerateTemplateValue;
                Type pt = property.PropertyType;
                if (pt.Equals(typeof(bool)))
                {
                    info.ConvertFunctionName = "Convert.ToBoolean";
                }
                else if (pt.Equals(typeof(byte)))
                {
                    info.ConvertFunctionName = "Convert.ToByte";
                }
                else if (pt.Equals(typeof(char)))
                {
                    info.ConvertFunctionName = "Convert.ToChar";
                }
                else if (pt.Equals(typeof(DateTime)))
                {
                    info.ConvertFunctionName = "Convert.ToDateTime";
                }
                else if (pt.Equals(typeof(decimal)))
                {
                    info.ConvertFunctionName = "Convert.ToDecimal";
                }
                else if (pt.Equals(typeof(double)))
                {
                    info.ConvertFunctionName = "Convert.ToDouble";
                }
                else if (pt.IsEnum)
                {
                    info.ConvertFunctionName = "(" + ToTypeNameCode(pt, true) + ")Convert.ToInt32";
                }
                else if (pt.Equals(typeof(Guid)))
                {
                    info.ConvertFunctionName = "(System.Guid)";
                }
                else if (pt.Equals(typeof(short)))
                {
                    info.ConvertFunctionName = "Convert.ToInt16";
                }
                else if (pt.Equals(typeof(int)))
                {
                    info.ConvertFunctionName = "Convert.ToInt32";
                }
                else if (pt.Equals(typeof(long)))
                {
                    info.ConvertFunctionName = "Convert.ToInt64";
                }
                else if (pt.Equals(typeof(sbyte)))
                {
                    info.ConvertFunctionName = "Convert.ToSByte";
                }
                else if (pt.Equals(typeof(float)))
                {
                    info.ConvertFunctionName = "Convert.ToSingle";
                }
                else if (pt.Equals(typeof(string)))
                {
                    info.ConvertFunctionName = "Convert.ToString";
                }
                else if (pt.Equals(typeof(ushort)))
                {
                    info.ConvertFunctionName = "Convert.ToUInt16";
                }
                else if (pt.Equals(typeof(uint)))
                {
                    info.ConvertFunctionName = "Convert.ToUInt32";
                }
                else if (pt.Equals(typeof(ulong)))
                {
                    info.ConvertFunctionName = "Convert.ToUInt64";
                }
                else if (pt.Equals(typeof(byte[])))
                {
                    info.ConvertFunctionName = "( byte[] ) ";
                }
                else
                {
                    info.ConvertFunctionName = "( " + ToTypeNameCode(pt, true) + " ) ";
                }
            }//foreach


            bool generateTempClass = true;
            foreach (ORMPropertyInfo p in type.Properties)
            {
                if (p.DelayLoad)
                {
                    generateTempClass = true;
                    break;
                }
            }
            if (generateTempClass == false)
            {
                if (type.Readonly == false)
                {
                    if (type.IsImplementInterface(typeof(IORMInstance)) == false)
                    {
                        generateTempClass = true;
                    }
                }
            }
            //string tempClassName = typeName + "_Temp";

            System.IO.StringWriter writer = new System.IO.StringWriter();
            string typeName2 = typeName;
            if (type.InstanceType.IsGenericTypeDefinition || type.InstanceType.IsGenericType)
            {
                typeName2 = typeName2.Replace("<", "_");
                typeName2 = typeName2.Replace(">", "_");
                typeName2 = typeName2.Replace(".", "_");
                typeName2 = typeName2.Replace(",", "_");
            }

            string tempTypeName = typeName2 + "_Temp";

            writer.WriteLine("public class " + typeName2 + "ORMTypeMappingHelper : " + typeof(ORMTypeMappingHelper).FullName);
            writer.WriteLine("{");
            writer.WriteLine("    public " + typeName2 + "ORMTypeMappingHelper()");
            writer.WriteLine("    {");
            writer.WriteLine("");
            writer.WriteLine("    }");
            writer.WriteLine("");
            writer.WriteLine("    public override bool SupportDelayLoad");
            writer.WriteLine("    {");
            writer.WriteLine("        get");
            writer.WriteLine("        {");
            writer.WriteLine("            return true;");
            writer.WriteLine("        }");
            writer.WriteLine("    }");
            writer.WriteLine("");
            writer.WriteLine("    public override Type InstanceType");
            writer.WriteLine("    {");
            writer.WriteLine("        get");
            writer.WriteLine("        {");
            if (generateTempClass)
            {
                writer.WriteLine("            return typeof(" + tempTypeName + ");");
            }
            else
            {
                writer.WriteLine("            return typeof(" + fullTypeName + " );");
            }
            writer.WriteLine("        }");
            writer.WriteLine("    }");
            writer.WriteLine("");
            writer.WriteLine("    public override object CreateInstance()");
            writer.WriteLine("    {");
            if (generateTempClass)
            {
                writer.WriteLine("        return new " + tempTypeName + "( );");
            }
            else
            {
                writer.WriteLine("        return new " + fullTypeName + "( );");
            }
            writer.WriteLine("    }");
            writer.WriteLine("");
            writer.WriteLine("////////////////////////////////////////////////////////////////////////////////");
            writer.WriteLine("");
            writer.WriteLine("    public override bool FillInstance(ORMContext context, IDataReader reader, object instance, List<RelationPropertyValue> relationValues)");
            writer.WriteLine("    {");
            writer.WriteLine("        " + fullTypeName + " obj = (" + fullTypeName + ")instance;");
            writer.WriteLine("            if (obj is " + typeof(IORMInstance).FullName + " )");
            writer.WriteLine("            {");
            writer.WriteLine("                " + typeof(IORMInstance).FullName + " oi = (" + typeof(IORMInstance).FullName + ")obj;");
            writer.WriteLine("                oi.ORMEngine = context.Engine;");
            writer.WriteLine("                oi.ORMDataState = DataRowState.Unchanged;");
            writer.WriteLine("            }");
            writer.WriteLine("");
            writer.WriteLine("        int fieldCount = reader.FieldCount;");
            writer.WriteLine("        bool enableDelayLoad = context.Engine.Config.EnableDelayLoad;");
            writer.WriteLine("        for (int iCount = 0; iCount < fieldCount; iCount++)");
            writer.WriteLine("        {");
            writer.WriteLine("            string name = reader.GetName(iCount);");
            writer.WriteLine("            name = name.Trim().ToLower();");
            writer.WriteLine("            switch (name)");
            writer.WriteLine("            {");
            Hashtable fieldMap = new Hashtable();
            foreach (ORMPropertyInfo property in type.Properties)
            {
                string fieldName = property.RuntimeDBFieldName;
                if (Util.HasContent(fieldName))
                {
                    ArrayList list = (ArrayList)fieldMap[fieldName];
                    if (list == null)
                    {
                        list = new ArrayList();
                        fieldMap[fieldName] = list;
                    }
                    list.Add(property);
                }
                fieldName = property.ComparabilityDBFieldName;
                if (Util.HasContent(fieldName))
                {
                    ArrayList list = (ArrayList)fieldMap[fieldName];
                    if (list == null)
                    {
                        list = new ArrayList();
                        fieldMap[fieldName] = list;
                    }
                    list.Add(property);
                }

                fieldName = property.ComparabilityDBFieldName2;
                if (Util.HasContent(fieldName))
                {
                    ArrayList list = (ArrayList)fieldMap[fieldName];
                    if (list == null)
                    {
                        list = new ArrayList();
                        fieldMap[fieldName] = list;
                    }
                    list.Add(property);
                }
            }
            foreach (string fieldName in fieldMap.Keys)
            {
                writer.WriteLine("                case \"" + fieldName.Trim().ToLower() + "\":");
                writer.WriteLine("                {");
                ArrayList ps = (ArrayList)fieldMap[fieldName];
                foreach (ORMPropertyInfo property in ps)
                {
                    if (property.HasRelation)
                    {
                        if (property.DelayLoad)
                        {
                            ORMRelationInfo relation = property.Relation;
                            writer.WriteLine("                    if( enableDelayLoad )");
                            writer.WriteLine("                    {");
                            if (relation.RuntimeStyle == ORMRelationStyle.OneToManyWithKeyList
                                || relation.RuntimeStyle == ORMRelationStyle.OneToOne)
                            {
                                if (relation.ParentProperty == property)
                                {
                                    writer.WriteLine("                        ( ( " + tempTypeName + " ) obj).DBValue_" + relation.ParentProperty.Name + " = reader.GetValue( iCount ) ;");
                                }
                            }
                            writer.WriteLine("                    }");
                            writer.WriteLine("                    else");
                            writer.WriteLine("                    {");
                            writer.WriteLine("                        if( relationValues != null )relationValues.Add( new RelationPropertyValue( instance , this.ORMType.Properties[\""
                                + property.Name + "\"] , reader.GetValue( iCount ) ));");
                            writer.WriteLine("                    }");
                        }
                        else
                        {
                            writer.WriteLine("                   if( relationValues != null )relationValues.Add( new RelationPropertyValue( instance , this.ORMType.Properties[\""
                                + property.Name + "\"] , reader.GetValue( iCount ) ));");
                        }
                    }
                    else
                    {
                        Type pt = property.PropertyType;
                        if (pt.IsEnum)
                        {
                            if (referenceTypes != null
                                && referenceTypes.Contains(pt) == false)
                            {
                                referenceTypes.Add(pt);
                            }
                            writer.WriteLine("                    obj." + property.Name
                                + " = (" + ToTypeNameCode(pt, true) + " ) DBValueToEnum( reader.GetValue( iCount ) , typeof( "
                                + ToTypeNameCode(pt, true) + " ));");
                        }
                        else
                        {
                            string ptTypeName = null;
                            if (Util.IsDBPrimitiveType(pt))
                            {
                                ptTypeName = pt.Name;
                            }
                            else if (pt.Equals(typeof(byte[])))
                            {
                                ptTypeName = "Binary";
                            }
                            if (property.PropertyType.Equals(typeof(byte[])))
                            {
                                ptTypeName = "Binary";
                            }
                            if (ptTypeName == null)
                            {
                                throw new NotSupportedException(fullTypeName + "." + property.Name);
                            }
                            writer.WriteLine("                    obj." + property.Name
                                + " = DBValueTo" + ptTypeName
                                + " ( reader.GetValue( iCount ) , "
                                + ToStringValueCode(property.Format) + " );");
                        }
                    }
                }//foreach

                writer.WriteLine("                }");
                writer.WriteLine("                break;");
            }//foreach
            writer.WriteLine("            }//switch");
            writer.WriteLine("        }//for");
            writer.WriteLine("");
            writer.WriteLine("        return true;");
            writer.WriteLine("    }//");

            writer.WriteLine("");
            writer.WriteLine("////////////////////////////////////////////////////////////////////////////////");
            writer.WriteLine("    public override string GetPropertyCommandText(string propertyName)");
            writer.WriteLine("    {");
            writer.WriteLine("        if (propertyName == null || propertyName.Trim().Length == 0)");
            writer.WriteLine("        {");
            writer.WriteLine("            return null;");
            writer.WriteLine("        }");
            writer.WriteLine("        switch (propertyName.Trim().ToLower())");
            writer.WriteLine("        {");
            foreach (ORMPropertyInfo property in type.Properties)
            {
                string strSQL = helper.GetPropertyCommandText(property.Name);
                if (Util.HasContent(strSQL))
                {
                    writer.WriteLine("       case \"" + property.Name.ToLower() + "\": return " + ToStringValueCode(strSQL) + " ;");
                }
            }
            writer.WriteLine("        }");
            writer.WriteLine("        return null;");
            writer.WriteLine("    }");
            writer.WriteLine("");

            writer.WriteLine("////////////////////////////////////////////////////////////////////////////////");
            writer.WriteLine("    public override object GetDBValue(IDataReader reader, string propertyName)");
            writer.WriteLine("    {");
            writer.WriteLine("        if (propertyName == null || propertyName.Trim().Length == 0)");
            writer.WriteLine("        {");
            writer.WriteLine("            return DBNull.Value;");
            writer.WriteLine("        }");
            writer.WriteLine("        switch (propertyName.Trim().ToLower())");
            writer.WriteLine("        {");
            foreach (ORMPropertyInfo property in type.Properties)
            {
                if (property.HasRelation == false)
                {
                    writer.WriteLine("            case  \"" + property.Name.Trim().ToLower()
                        + "\": return InnerGetDBValue( reader , "
                        + ToStringValueCode(property.RuntimeDBFieldName) + " , "
                        + ToStringValueCode(property.ComparabilityDBFieldName) + " , "
                        + ToStringValueCode(property.ComparabilityDBFieldName2) + " );");
                }//if
            }//foreach
            writer.WriteLine("        }");
            writer.WriteLine("        return DBNull.Value;");
            writer.WriteLine("    }");
            writer.WriteLine("");

            writer.WriteLine("////////////////////////////////////////////////////////////////////////////////");
            writer.WriteLine("    public override void GenerateNewValue(ORMContext context , object instance )");
            writer.WriteLine("    {");
            writer.WriteLine("          " + fullTypeName + " record = ( " + fullTypeName + " ) instance ;");
            foreach (ORMPropertyInfo property in type.Properties)
            {
                if (property.NewValueGenerate != null)
                {
                    ORMNewValueGenerateInfo nvg = property.NewValueGenerate;
                    switch (property.NewValueGenerate.Style)
                    {
                        case ORMNewValueGenerateStyle.None:
                            break;
                        case ORMNewValueGenerateStyle.Increase:
                            writer.WriteLine("          record." + property.Name
                                + " = " + propertyInfos[property].ConvertFunctionName
                                + " ( context.Engine.GenerateIncreaseID( context , "
                                + ToStringValueCode(type.TableName) + " , "
                                + ToStringValueCode(property.RuntimeDBFieldName) + "));");
                            break;
                        case ORMNewValueGenerateStyle.CurrentDate:
                            if (property.PropertyType.Equals(typeof(DateTime)))
                            {
                                writer.WriteLine("        record." + property.Name + " = DateTime.Today ;");
                            }
                            else
                            {
                                if (Util.HasContent(nvg.Format))
                                {
                                    writer.WriteLine("         record." + property.Name + " = "
                                        + propertyInfos[property].ConvertFunctionName
                                        + " ( DateTime.ToDay.ToString(" + ToStringValueCode(nvg.Format)
                                        + " ));");
                                }
                                else
                                {
                                    writer.WriteLine("         record." + property.Name + " = "
                                        + propertyInfos[property].ConvertFunctionName
                                        + " ( DateTime.ToDay );");
                                }
                            }
                            break;
                        case ORMNewValueGenerateStyle.CurrentDateTime:
                            if (property.PropertyType.Equals(typeof(DateTime)))
                            {
                                writer.WriteLine("         record." + property.Name + " = DateTime.Now ;");
                            }
                            else
                            {
                                if (Util.HasContent(nvg.Format))
                                {
                                    writer.WriteLine("         record." + property.Name + " = "
                                        + propertyInfos[property].ConvertFunctionName
                                        + " ( DateTime.Now.ToString(" + ToStringValueCode(nvg.Format)
                                        + " ));");
                                }
                                else
                                {
                                    writer.WriteLine("         record." + property.Name + " = "
                                        + propertyInfos[property].ConvertFunctionName
                                        + " ( DateTime.Now );");
                                }
                            }
                            break;
                        case ORMNewValueGenerateStyle.GUID:
                            if (property.PropertyType.Equals(typeof(Guid)))
                            {

                                writer.WriteLine("           record." + property.Name + " = System.Guid.NewGuid();");
                            }
                            else
                            {
                                if (Util.HasContent(nvg.Format))
                                {
                                    writer.WriteLine("           record." + property.Name + " = "
                                            + propertyInfos[property].ConvertFunctionName
                                            + " ( System.Guid.NewGuid().ToString(" + ToStringValueCode(nvg.Format) + "));");
                                }
                                else
                                {
                                    writer.WriteLine("           record." + property.Name + " = "
                                            + propertyInfos[property].ConvertFunctionName
                                            + " ( System.Guid.NewGuid() );");
                                }
                            }
                            break;
                        case ORMNewValueGenerateStyle.LocalMethod:
                            string methodName = "Generate_" + property.Name;
                            if (Util.HasContent(nvg.Format))
                            {
                                methodName = nvg.Format.Trim();
                            }
                            System.Reflection.MethodInfo method = type.InstanceType.GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
                            if (method != null)
                            {
                                writer.WriteLine("            record." + method.Name + " ( );");
                            }
                            else
                            {
                                throw new InvalidOperationException("miss " + fullTypeName + "." + methodName);
                            }
                            break;
                        case ORMNewValueGenerateStyle.Custom:
                            writer.WriteLine("            record." + property.Name + " = "
                                + propertyInfos[property].ConvertFunctionName
                                + " ( context.Engine.ExecuteCustomHandler( " + ToStringValueCode(nvg.Format)
                                + " , instance , null );");
                            break;
                    }//switch
                }//if
            }//foreach

            writer.WriteLine("    }");
            writer.WriteLine("");

            writer.WriteLine("////////////////////////////////////////////////////////////////////////////////");
            writer.WriteLine("    public override object GetKeyValue(object instance)");
            writer.WriteLine("    {");
            if (type.KeyProperty == null)
            {
                writer.WriteLine("     throw new NotSupportedException( "
                    + ToStringValueCode(fullTypeName + ".GetKeyValue") + ");");
            }
            else
            {
                writer.WriteLine("     return (( " + fullTypeName + ") instance)." + type.KeyProperty.Name + ";");
            }
            writer.WriteLine("    }");
            writer.WriteLine("");

            writer.WriteLine("////////////////////////////////////////////////////////////////////////////////");
            writer.WriteLine("    public override object GetPropertyValue(object instance, string propertyName)");
            writer.WriteLine("    {");
            writer.WriteLine("        if (propertyName == null || propertyName.Trim().Length == 0)");
            writer.WriteLine("        {");
            writer.WriteLine("            throw new ArgumentNullException(\"propertyName\");");
            writer.WriteLine("        }");
            writer.WriteLine("        if (instance == null)");
            writer.WriteLine("        {");
            writer.WriteLine("            throw new ArgumentNullException(\"instance\");");
            writer.WriteLine("        }");
            writer.WriteLine("        " + fullTypeName + " obj = (" + fullTypeName + ")instance;");
            writer.WriteLine("        switch (propertyName.Trim().ToLower())");
            writer.WriteLine("        {");
            foreach (ORMPropertyInfo property in type.Properties)
            {
                writer.WriteLine("            case \"" + property.Name.ToLower() + "\" : return obj." + property.Name + ";");
            }
            writer.WriteLine("            default:");
            writer.WriteLine("                throw new NotSupportedException(propertyName);");
            writer.WriteLine("        }");
            writer.WriteLine("    }");
            writer.WriteLine("");

            writer.WriteLine("////////////////////////////////////////////////////////////////////////////////");
            writer.WriteLine("    public override void SetPropertyValue(object instance, string propertyName, object Value)");
            writer.WriteLine("    {");
            writer.WriteLine("        if (propertyName == null || propertyName.Trim().Length == 0)");
            writer.WriteLine("        {");
            writer.WriteLine("            throw new ArgumentNullException(\"propertyName\");");
            writer.WriteLine("        }");
            writer.WriteLine("        if (instance == null)");
            writer.WriteLine("        {");
            writer.WriteLine("            throw new ArgumentNullException(\"instance\");");
            writer.WriteLine("        }");
            writer.WriteLine("        " + fullTypeName + " obj = (" + fullTypeName + ")instance;");
            writer.WriteLine("        switch (propertyName.Trim().ToLower())");
            writer.WriteLine("        {");
            foreach (ORMPropertyInfo property in type.Properties)
            {
                Type pt = property.PropertyType;
                string functionName = propertyInfos[property].ConvertFunctionName;

                writer.WriteLine("          case \"" + property.Name.ToLower() + "\":");
                writer.WriteLine("                obj." + property.Name + " = " + functionName + " ( Value ) ;");
                writer.WriteLine("                break;");
            }//foreach
            writer.WriteLine("            default:");
            writer.WriteLine("                throw new NotSupportedException(propertyName);");
            writer.WriteLine("        }");
            writer.WriteLine("    }");
            writer.WriteLine("");
            writer.WriteLine("");


            ORMDBCommand tempCommand = new ORMDBCommand();
            context.Command = tempCommand;
            context.ForGenerateCode = true;

            writer.WriteLine("////////////////////////////////////////////////////////////////////////////////");
            writer.WriteLine("    public override bool PrepareDeleteCommand(ORMContext context, object instance)");
            writer.WriteLine("    {");
            writer.WriteLine("        " + fullTypeName + " obj = (" + fullTypeName + ")instance;");
            writer.WriteLine("        context.Command.Parameters.Clear();");
            tempCommand.Parameters.Clear();
            helper.PrepareDeleteCommand(context, null);
            WriteCommandCode(writer, tempCommand, "context.Command", "obj", null);
            writer.WriteLine("        return true;");
            writer.WriteLine("    }");
            writer.WriteLine("");

            writer.WriteLine("////////////////////////////////////////////////////////////////////////////////");
            writer.WriteLine("    public override bool PrepareInsertCommand(ORMContext context, object instance)");
            writer.WriteLine("    {");
            writer.WriteLine("        " + fullTypeName + " obj = (" + fullTypeName + ")instance;");
            writer.WriteLine("        context.Command.Parameters.Clear();");
            tempCommand.Parameters.Clear();
            helper.PrepareInsertCommand(context, null);
            WriteCommandCode(writer, tempCommand, "context.Command", "obj", null);
            writer.WriteLine("        return true;");
            writer.WriteLine("    }");
            writer.WriteLine("");

            writer.WriteLine("////////////////////////////////////////////////////////////////////////////////");
            writer.WriteLine("    public override bool PrepareUpdateCommand(ORMContext context, object instance)");
            writer.WriteLine("    {");
            writer.WriteLine("        " + fullTypeName + " obj = ( " + fullTypeName + ")instance;");
            writer.WriteLine("        context.Command.Parameters.Clear();");

            context.ForGenerateCode = true;
            helper.PrepareUpdateCommand(context, null);
            WriteCommandCode(writer, tempCommand, "context.Command", "obj", null);
            writer.WriteLine("        return true;");
            writer.WriteLine("    }");
            writer.WriteLine("");

            writer.WriteLine("////////////////////////////////////////////////////////////////////////////////");
            writer.WriteLine("    public override string SelectCommandText");
            writer.WriteLine("    {");
            writer.WriteLine("        get");
            writer.WriteLine("        {");
            writer.WriteLine("            return " + ToStringValueCode(helper.SelectCommandText) + ";");
            writer.WriteLine("        }");
            writer.WriteLine("    }");
            writer.WriteLine("");

            ArrayList orderProperties = new ArrayList();
            foreach (ORMPropertyInfo property in type.Properties)
            {
                if (property.SortStyle == ORMSortStyle.Ascent
                    || property.SortStyle == ORMSortStyle.Descent)
                {
                    orderProperties.Add(property);
                }
            }//foreach
            if (orderProperties.Count > 1)
            {
                orderProperties.Sort(new SortPriorityComparer());
                StringBuilder myOrderCommand = new StringBuilder();
                foreach (ORMPropertyInfo property in orderProperties)
                {
                    if (myOrderCommand.Length > 0)
                    {
                        myOrderCommand.Append(" , ");
                    }
                    if (property.SortStyle == ORMSortStyle.Ascent)
                    {
                        myOrderCommand.Append(type.TableName + "." + property.RuntimeDBFieldName + " Asc ");
                    }
                    else
                    {
                        myOrderCommand.Append(type.TableName + "." + property.RuntimeDBFieldName + " Desc ");
                    }
                }
                if (myOrderCommand.Length > 0)
                {
                    writer.WriteLine("////////////////////////////////////////////////////////////////////////////////");
                    writer.WriteLine("    public override string OrderCommandText");
                    writer.WriteLine("    {");
                    writer.WriteLine("        get");
                    writer.WriteLine("        {");
                    writer.WriteLine("            return " + ToStringValueCode(myOrderCommand.ToString()) + ";");
                    writer.WriteLine("        }");
                    writer.WriteLine("    }");
                    writer.WriteLine("");
                }
            }//if

            writer.WriteLine("/////////////////////////////////////////////////");
            writer.WriteLine("    public override System.Data.DataTable CreateDataTable()");
            writer.WriteLine("    {");
            writer.WriteLine("        System.Data.DataTable table = new System.Data.DataTable();");
            writer.WriteLine("        System.Data.DataColumn column = null;");
            Dictionary<string, ORMPropertyInfo> dataProperties = new Dictionary<string, ORMPropertyInfo>();
            foreach (ORMPropertyInfo property in type.Properties)
            {
                if (property.Ignore)
                {
                    continue;
                }
                string fieldName = property.RuntimeDBFieldName ;
                if (dataProperties.ContainsKey( fieldName ))
                {
                    continue;
                }
                ORMRelationStyle rs = ORMRelationStyle.None;
                if (property.Relation != null)
                {
                    rs = property.Relation.RuntimeStyle;
                    if (rs == ORMRelationStyle.OneToManyWithKeyList || rs == ORMRelationStyle.OneToOne)
                    {
                    }
                    else
                    {
                        continue;
                    }
                }
               
                writer.WriteLine("        column = new System.Data.DataColumn();");
                writer.WriteLine("        column.ColumnName = " + ToStringValueCode(fieldName) + ";");
                if (Util.HasContent(property.Description))
                {
                    writer.WriteLine("        column.Caption = " + ToStringValueCode(property.Description) + ";");
                }
                else
                {
                    writer.WriteLine("        column.Caption = " + ToStringValueCode(fieldName) + ";");
                }

                switch (property.DBValueType)
                {
                    case ORMDBValueType.Binary :
                        writer.WriteLine("        column.DataType = typeof( byte[]);");
                        break;
                    case ORMDBValueType.DateTime :
                        writer.WriteLine("        column.DataType = typeof( DateTime );");
                        break;
                    case ORMDBValueType.Integer :
                        writer.WriteLine("        column.DataType = typeof( int );");
                        break;
                    case ORMDBValueType.Numeric :
                        writer.WriteLine("        column.DataType = typeof( double );");
                        break;
                    case ORMDBValueType.Text :
                        writer.WriteLine("        column.DataType = typeof( string );");
                        break;
                    default :
                        if (Util.IsDBPrimitiveType(property.PropertyType))
                        {
                            writer.WriteLine("        column.DataType = typeof( " + ToTypeNameCode(property.PropertyType, true) + " );");
                        }
                        else
                        {
                            if (rs == ORMRelationStyle.OneToOne)
                            {
                                writer.WriteLine("        column.DataType = typeof( " + ToTypeNameCode(property.Relation.ChildProperty.PropertyType , true ) + " );");
                            }
                            else if (rs == ORMRelationStyle.OneToManyWithKeyList)
                            {
                                writer.WriteLine("        column.DataType = typeof( string );");
                            }
                        }
                        break;
                }//switch
                
                if (property.KeyField)
                {
                    writer.WriteLine("        column.AllowDBNull = false;");
                    writer.WriteLine("        column.Unique = true;");
                }
                writer.WriteLine("        table.Columns.Add( column );");
                dataProperties[ fieldName ] = property ;
            }//foreach
            writer.WriteLine("        return table;");
            writer.WriteLine("    }");
            writer.WriteLine();
            writer.WriteLine("///////////////////////////////////////////////////////");
            writer.WriteLine("    public override System.Data.DataRow CreateDataRow(System.Data.DataTable table , object instance)");
            writer.WriteLine("    {");
            writer.WriteLine("        if( instance == null ) throw new ArgumentNullException(\"instance\");");
            writer.WriteLine("        " + fullTypeName + "   myRecord = (" + fullTypeName + ") instance ;");
            writer.WriteLine("        System.Data.DataRow newRow = table.NewRow();");
            foreach( string fieldName in dataProperties.Keys )
            {
                ORMPropertyInfo property = dataProperties[ fieldName ] ;
                if (property.Relation != null)
                {
                    ORMRelationStyle rs = property.Relation.RuntimeStyle;
                    if (rs == ORMRelationStyle.OneToOne)
                    {
                        writer.WriteLine("        newRow[" + ToStringValueCode(fieldName) + "] = ( myRecord." + property.Name + " == null ? (object) DBNull.Value : (object)myRecord." + property.Name + "." + property.Relation.ChildProperty.Name + " );");
                        continue;
                    }
                    else if (rs == ORMRelationStyle.OneToManyWithKeyList)
                    {
                        //writer.WriteLine("        newRow[" + ToStringValueCode( fieldName ) + "] = myRecord." + property.Name + " == null ? DBNull.Value : base.GetKeyValueList( null , 
                        continue;
                    }
                }
                writer.WriteLine("        newRow[" + ToStringValueCode(fieldName) + "] = myRecord." + property.Name + " ;");
            }//foreach

            writer.WriteLine("        return newRow ;");
            writer.WriteLine("    }");
            writer.WriteLine();

            if (generateTempClass)
            {
                bool isImplementIEditableObject = type.IsImplementInterface(
                    typeof(System.ComponentModel.IEditableObject));

                writer.WriteLine("////////////////////////////////////////////////////////////////////////////////");
                writer.WriteLine("    [Serializable()]");
                writer.WriteLine("    [System.Xml.Serialization.XmlTypeAttribute( " + ToStringValueCode(type.XmlTypeName) + ")]");
                writer.WriteLine("    public class " + tempTypeName + " : " + ToTypeNameCode(type.InstanceType, true));
                if (type.IsImplementInterface(typeof(IORMInstance)) == false)
                {
                    writer.WriteLine("                            , " + typeof(IORMInstance).FullName);
                }
                writer.WriteLine("    {");
                writer.WriteLine("        public " + tempTypeName + "( )");
                writer.WriteLine("        {");
                writer.WriteLine("        }");
                writer.WriteLine("");
                foreach (ORMPropertyInfo property in type.Properties)
                {
                    if (property.DelayLoad == false)
                    {
                        if (property.Overrideable)
                        {
                            writer.WriteLine("");
                            writer.WriteLine("            public override " + ToTypeNameCode(property.PropertyType, true) + " " + property.Name);
                            writer.WriteLine("            {");
                            writer.WriteLine("                get");
                            writer.WriteLine("                {");
                            writer.WriteLine("                    return base." + property.Name + ";");
                            writer.WriteLine("                }");
                            writer.WriteLine("                set");
                            writer.WriteLine("                {");
                            writer.WriteLine("                    base." + property.Name + " = value;");
                            writer.WriteLine("                    ORMOnValueChanged();");
                            writer.WriteLine("                }");
                            writer.WriteLine("            }");
                        }
                        continue;
                    }
                    writer.WriteLine("");
                    ORMRelationInfo relation = property.Relation;
                    Type pt = property.PropertyType;
                    //bool generateTempValue = false;

                    if (Util.IsDBPrimitiveType(pt))
                    {
                        writer.WriteLine("        internal bool LoadFlag_" + property.Name + " = false;");
                    }
                    else if (property.GenerateTemplateValue)
                    {
                        writer.WriteLine("        internal object DBValue_" + property.Name + " = null;");
                    }

                    writer.WriteLine("        /// <summary>");
                    writer.WriteLine("        /// Handle delay load");
                    writer.WriteLine("        /// </summary>");
                    writer.WriteLine("        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]");
                    writer.WriteLine("        public override " + ToTypeNameCode(pt, true) + " " + property.Name);
                    writer.WriteLine("        {");
                    writer.WriteLine("            get");
                    writer.WriteLine("            {");
                    if (Util.IsDBPrimitiveType(pt))
                    {
                        writer.WriteLine("                if( this._ORMDataState != DataRowState.Added && this._ORMEngine != null && this.LoadFlag_" + property.Name + " == false )");
                        writer.WriteLine("                {");
                        writer.WriteLine("                    this.LoadFlag_" + property.Name + " = true ;");
                        tempCommand.Parameters.Clear();
                        StringBuilder strSQL = new StringBuilder();
                        strSQL.Append("Select " + property.RuntimeDBFieldName + " From " + type.TableName + " Where " + type.KeyDBFieldName + " = ");
                        ORMDBCommand.AppendParameterSQL(strSQL, type.KeyDBFieldName, type.KeyProperty, context.Engine.Config.ParameterStyle, tempCommand);
                        tempCommand.CommandText = strSQL.ToString();
                        writer.WriteLine("                    using(ORMDBCommand cmd = new ORMDBCommand( ))");
                        writer.WriteLine("                    {");
                        WriteCommandCode(writer, tempCommand, "cmd", "this", property.Name);
                        writer.WriteLine("                         object dbValue = this._ORMEngine.ExecuteScalar( cmd );");
                        if (pt.IsEnum)
                        {
                            if (referenceTypes != null
                                && referenceTypes.Contains(pt) == false)
                            {
                                referenceTypes.Add(pt);
                            }
                            writer.WriteLine("                    base." + property.Name
                                + " = (" + ToTypeNameCode(pt, true) + " ) XDesigner.ORM.DOM.ORMTypeMappingHelper.DBValueToEnum( dbValue , typeof( "
                                + ToTypeNameCode(pt, true) + " ));");
                        }
                        else
                        {
                            string ptTypeName = null;
                            if (pt.Equals(typeof(byte[])))
                            {
                                ptTypeName = "Binary";
                            }
                            else
                            {
                                ptTypeName = pt.Name;
                            }
                            if (ptTypeName == null)
                            {
                                throw new NotSupportedException(fullTypeName + "." + property.Name);
                            }
                            writer.WriteLine("                    base." + property.Name
                                + " = XDesigner.ORM.DOM.ORMTypeMappingHelper.DBValueTo" + ptTypeName
                                + " ( dbValue , "
                                + ToStringValueCode(property.Format) + " );");
                        }
                        writer.WriteLine("                    }//using");

                        //writer.WriteLine("                    cmd.CommandText = " + ToStringValueCode( "Select " + property.RuntimeDBFieldName + " From " + type.TableName + " Where 

                        writer.WriteLine("                }//if");
                        writer.WriteLine("                return base." + property.Name + ";");
                        writer.WriteLine("            }");
                        writer.WriteLine("            set");
                        writer.WriteLine("            {");
                        writer.WriteLine("                base." + property.Name + " = value;");
                        writer.WriteLine("                this.LoadFlag_" + property.Name + " = true ;");
                        writer.WriteLine("                ORMOnValueChanged();");
                        writer.WriteLine("            }");
                        writer.WriteLine("        }");
                    }
                    else
                    {
                        if (property.GenerateTemplateValue)
                        {
                            writer.WriteLine("                if (  this._ORMDataState != DataRowState.Added && base."
                                + property.Name + " == null && this._ORMEngine != null && this.DBValue_"
                                + property.Name + " != null && DBNull.Value.Equals( this.DBValue_"
                                + property.Name + " ) == false )");
                        }
                        else
                        {
                            writer.WriteLine("                if (  this._ORMDataState != DataRowState.Added && base." + property.Name + " == null && this._ORMEngine != null )");
                        }
                        writer.WriteLine("                {");
                        bool logOuterReference = false;
                        string strCustomCommandText = property.CommandText;
                        if (relation != null && relation.RuntimeStyle == ORMRelationStyle.OneToMany)
                        {
                            Type itemType = CollectionTypeHelper.GetElementType(pt);
                            writer.WriteLine("");
                            writer.WriteLine("                    " + ToTypeNameCode(itemType, true) + " conditionInstance = new " + ToTypeNameCode(itemType, true) + "();");
                            string fieldList = null;
                            if (relation.ChildProperty != null)
                            {
                                fieldList = ToStringValueCode(relation.ChildProperty.Name);
                                if (relation.ChildProperty.PropertyType.Equals(type.InstanceType))
                                {
                                    writer.WriteLine("                    conditionInstance." + relation.ChildProperty.Name + " = this;");
                                }
                                else
                                {
                                    writer.WriteLine("                    conditionInstance." + relation.ChildProperty.Name + " = this." + relation.ParentProperty.Name + " ;");
                                }
                                foreach (ORMPropertyInfo p2 in relation.ChildProperty.OwnerType.Properties)
                                {
                                    if (p2.ExtCondition == ORMBooleanValue.True)
                                    {
                                        fieldList = fieldList + "," + ToStringValueCode(p2.Name);
                                    }
                                }
                            }
                            else
                            {
                                throw new NotSupportedException(fullTypeName + "." + property.Name + " Delay load");
                            }

                            writer.WriteLine("");
                            writer.WriteLine("                    Array list = this._ORMEngine.ReadInstancesByCondition(");
                            writer.WriteLine("                        conditionInstance,");
                            writer.WriteLine("                        new string[] { " + fieldList + " });");
                            writer.WriteLine("");
                            writer.WriteLine("                    " + ToTypeNameCode(pt, true) + " result = new " + ToTypeNameCode(pt, true) + "();");
                            writer.WriteLine("");
                            writer.WriteLine("                    foreach (" + ToTypeNameCode(itemType, true) + " item in list)");
                            writer.WriteLine("                    {");
                            writer.WriteLine("                        result.Add(item);");
                            ORMTypeInfo opt = context.Engine.Project.Types[itemType];
                            if (opt != null)
                            {
                                foreach (ORMPropertyInfo p2 in opt.Properties)
                                {
                                    if (p2.ParentReference == ORMBooleanValue.True)
                                    {
                                        if (p2.PropertyType.Equals(type) || type.InstanceType.IsSubclassOf(p2.PropertyType))
                                        {
                                            writer.WriteLine("                   item." + p2.Name + " = this ;");
                                        }
                                    }
                                }
                                if (relation.LogReference && opt.LogReference == ORMBooleanValue.True)
                                {
                                    if (context.Engine.IsBuffered(opt))
                                    {
                                        logOuterReference = true;
                                        writer.WriteLine("                        this._ORMEngine.Buffer.AddOuterReference(item , result , null); ");
                                    }
                                }
                            }//if
                            writer.WriteLine("                    }");
                            writer.WriteLine("");
                            writer.WriteLine("                    base." + property.Name + " = result;");
                        }
                        else if (relation != null && relation.RuntimeStyle == ORMRelationStyle.OneToManyWithKeyList)
                        {
                            Type itemType = CollectionTypeHelper.GetElementType(pt);
                            string commandText = helper.GetPropertyCommandText(property.Name);
                            writer.WriteLine("                    " + typeof(ORMDBCommand).FullName + " command = new " + typeof(ORMDBCommand).FullName + "();");
                            writer.WriteLine();
                            writer.Write("                   command.CommandText = ");
                            string[] items = XDesigner.Common.VariableString.AnalyseVariableString(commandText, "[%", "%]");
                            for (int iCount = 0; iCount < items.Length; iCount++)
                            {
                                if (iCount > 0)
                                {
                                    writer.Write(" + ");
                                }
                                if ((iCount % 2) == 0)
                                {
                                    writer.Write(ToStringValueCode(items[iCount]));
                                }
                                else
                                {
                                    string item = items[iCount];
                                    if (item.StartsWith("@"))
                                    {
                                        item = item.Substring(1);
                                    }
                                    ORMPropertyInfo pp = type.Properties[item];
                                    if (pp != null)
                                    {
                                        if (pp.GenerateTemplateValue)
                                        {
                                            writer.Write("this.DBValue_" + pp.Name);
                                        }
                                        else
                                        {
                                            writer.Write("this." + pp.Name);
                                        }
                                    }
                                }
                            }//for
                            writer.Write(";");
                            writer.WriteLine();
                            writer.WriteLine("                    Array list = this._ORMEngine.ReadInstances( typeof( " + ToTypeNameCode(itemType, true) + " ) , command );");
                            writer.WriteLine("                    " + ToTypeNameCode(pt, true) + " result = new " + ToTypeNameCode(pt, true) + "();");
                            writer.WriteLine("");
                            writer.WriteLine("                    foreach (" + ToTypeNameCode(itemType, true) + " item in list)");
                            writer.WriteLine("                    {");
                            writer.WriteLine("                        result.Add(item);");
                            ORMTypeInfo opt = context.Engine.Project.Types[itemType];
                            if (opt != null)
                            {
                                foreach (ORMPropertyInfo p2 in opt.Properties)
                                {
                                    if (p2.ParentReference == ORMBooleanValue.True)
                                    {
                                        if (p2.PropertyType.Equals(type) || type.InstanceType.IsSubclassOf(p2.PropertyType))
                                        {
                                            writer.WriteLine("                   item." + p2.Name + " = this ;");
                                        }
                                    }
                                }
                                if (relation.LogReference && opt.LogReference == ORMBooleanValue.True)
                                {
                                    if (context.Engine.IsBuffered(opt))
                                    {
                                        logOuterReference = true;
                                        writer.WriteLine("                        this._ORMEngine.Buffer.AddOuterReference(item , result , null); ");
                                    }
                                }
                            }
                            writer.WriteLine("                    }");
                            writer.WriteLine("");
                            writer.WriteLine("                    base." + property.Name + " = result;");
                        }
                        else if (relation != null && relation.RuntimeStyle == ORMRelationStyle.OnetoManyExt)
                        {
                            Type itemType = CollectionTypeHelper.GetElementType(pt);
                            writer.WriteLine("");
                            writer.WriteLine("                   " + ToTypeNameCode(pt, true) + " result = new " + ToTypeNameCode(pt, true) + "();");
                            writer.WriteLine("");
                            writer.WriteLine("                   Array list = this._ORMEngine.ReadInstancesByStandardRelation( this , typeof( " + ToTypeNameCode(itemType, true) + " ) );");
                            writer.WriteLine("");
                            writer.WriteLine("                   if( list != null && list.Length > 0 )");
                            writer.WriteLine("                   {");
                            writer.WriteLine("                        foreach (" + ToTypeNameCode(itemType, true) + " item in list)");
                            writer.WriteLine("                        {");
                            writer.WriteLine("                            result.Add(item);");
                            writer.WriteLine("                        }");
                            writer.WriteLine("                    }");
                            writer.WriteLine("");
                            writer.WriteLine("                    base." + property.Name + " = result;");
                        }
                        else if (relation != null && relation.RuntimeStyle == ORMRelationStyle.OneToOne)
                        {
                            writer.WriteLine("                    base." + property.Name + " = ( " + ToTypeNameCode(property.PropertyType, true) + " )this._ORMEngine.ReadInstance( typeof( " + ToTypeNameCode(property.PropertyType, true) + ") , this.DBValue_" + property.Name + ");");

                            ORMTypeInfo opt = context.Engine.Project.Types[pt];
                            if (opt != null && relation.LogReference && opt.LogReference == ORMBooleanValue.True)
                            {
                                if (context.Engine.IsBuffered(opt))
                                {
                                    logOuterReference = true;
                                    writer.WriteLine("                        if( base." + property.Name + " != null ) this._ORMEngine.Buffer.AddOuterReference( base." + property.Name + " , this , \"" + property.Name + "\"); ");
                                }
                            }
                        }
                        writer.WriteLine("                }");
                        writer.WriteLine("                return base." + property.Name + ";");
                        writer.WriteLine("            }");
                        writer.WriteLine("            set");
                        writer.WriteLine("            {");
                        if (relation != null && relation.RuntimeStyle == ORMRelationStyle.OneToOne)
                        {
                            //ORMTypeInfo opt = context.Engine.Project.Types[pt];

                            writer.WriteLine("              if( base." + property.Name + " != value )");
                            writer.WriteLine("              {");
                            if (logOuterReference)
                            {
                                writer.WriteLine("                     object objBack = base." + property.Name + ";");
                            }

                            writer.WriteLine("                     base." + property.Name + " = value ;");
                            if (property.GenerateTemplateValue)
                            {
                                writer.WriteLine("                     this.DBValue_" + property.Name + " = DBNull.Value ;");
                            }
                            if (logOuterReference)
                            {
                                writer.WriteLine("                     if( this._ORMEngine != null && " + typeof(ORMInstanceBuffer).FullName + ".RunningDeleteOuterReference == false )");
                                writer.WriteLine("                     {");
                                writer.WriteLine("                          if( objBack != null ) this._ORMEngine.Buffer.RemoveOuterReferenceInfo( objBack , this );");
                                writer.WriteLine("                          if( value != null   ) this._ORMEngine.Buffer.AddOuterReference       ( value , this , \"" + property.Name + "\" );");
                                writer.WriteLine("                     }");
                            }
                            if (isImplementIEditableObject == false)
                            {
                                writer.WriteLine("                     ORMOnValueChanged();");
                            }
                            writer.WriteLine("               }");
                        }
                        else
                        {
                            writer.WriteLine("                base." + property.Name + " = value;");
                            if (property.GenerateTemplateValue)
                            {
                                writer.WriteLine("                this.DBValue_" + property.Name + " = DBNull.Value ;");
                            }
                            if (isImplementIEditableObject == false)
                            {
                                writer.WriteLine("                ORMOnValueChanged();");
                            }
                        }
                        writer.WriteLine("            }");
                        writer.WriteLine("        }");
                    }//else
                }//foreach

                if (type.IsImplementInterface(typeof(IORMInstance)) == false)
                {
                    writer.WriteLine("");
                    writer.WriteLine("            private System.Data.DataRowState _ORMDataState = DataRowState.Unchanged;");
                    writer.WriteLine("            [System.ComponentModel.Browsable( false )]");
                    writer.WriteLine("            [System.Xml.Serialization.XmlIgnore()]");
                    writer.WriteLine("            DataRowState IORMInstance.ORMDataState");
                    writer.WriteLine("            {");
                    writer.WriteLine("                get");
                    writer.WriteLine("                {");
                    writer.WriteLine("                    return _ORMDataState;");
                    writer.WriteLine("                }");
                    writer.WriteLine("                set");
                    writer.WriteLine("                {");
                    writer.WriteLine("                    _ORMDataState = value;");
                    writer.WriteLine("                }");
                    writer.WriteLine("            }");
                    writer.WriteLine("");
                    writer.WriteLine("            [NonSerialized()]");
                    writer.WriteLine("            private XDesigner.ORM.ORMEngine _ORMEngine = null;");
                    writer.WriteLine("");
                    writer.WriteLine("            [System.ComponentModel.Browsable(false)]");
                    writer.WriteLine("            [System.Xml.Serialization.XmlIgnore()]");
                    writer.WriteLine("            XDesigner.ORM.ORMEngine IORMInstance.ORMEngine");
                    writer.WriteLine("            {");
                    writer.WriteLine("                get { return _ORMEngine; }");
                    writer.WriteLine("                set { _ORMEngine = value; }");
                    writer.WriteLine("            }");
                    writer.WriteLine("");
                }

                if (isImplementIEditableObject == false)
                {
                    writer.WriteLine("            private void ORMOnValueChanged()");
                    writer.WriteLine("            {");
                    writer.WriteLine("                if (_ORMValueBack != null)");
                    writer.WriteLine("                {");
                    writer.WriteLine("                    if (_ORMDataState == DataRowState.Unchanged)");
                    writer.WriteLine("                    {");
                    writer.WriteLine("                        _ORMDataState = DataRowState.Modified;");
                    writer.WriteLine("                    }");
                    writer.WriteLine("                }");
                    writer.WriteLine("            }");
                    writer.WriteLine("            private " + fullTypeName + " _ORMValueBack = null;");
                    writer.WriteLine("");
                    writer.WriteLine("            void System.ComponentModel.IEditableObject.BeginEdit()");
                    writer.WriteLine("            {");
                    writer.WriteLine("                _ORMValueBack = new " + fullTypeName + "();");
                    foreach (ORMPropertyInfo property in type.Properties)
                    {
                        writer.WriteLine("                _ORMValueBack." + property.Name + " = base." + property.Name + " ;");
                    }
                    writer.WriteLine("            }");
                    writer.WriteLine("");
                    writer.WriteLine("            void System.ComponentModel.IEditableObject.CancelEdit()");
                    writer.WriteLine("            {");
                    writer.WriteLine("                if (_ORMValueBack != null)");
                    writer.WriteLine("                {");
                    foreach (ORMPropertyInfo property in type.Properties)
                    {
                        writer.WriteLine("                    base." + property.Name + " = _ORMValueBack." + property.Name + " ;");
                    }
                    writer.WriteLine("                }");
                    writer.WriteLine("                _ORMValueBack = null;");
                    writer.WriteLine("            }");
                    writer.WriteLine("");
                    writer.WriteLine("            void System.ComponentModel.IEditableObject.EndEdit()");
                    writer.WriteLine("            {");
                    writer.WriteLine("                _ORMValueBack = null;");
                    writer.WriteLine("                if ( _ORMEngine != null && _ORMEngine.Config.UpdateImmediately == true )");
                    writer.WriteLine("                {");
                    writer.WriteLine("                    if (_ORMDataState == DataRowState.Added)");
                    writer.WriteLine("                    {");
                    writer.WriteLine("                        if ( _ORMEngine.Insert(this) > 0)");
                    writer.WriteLine("                        {");
                    writer.WriteLine("                            _ORMDataState = DataRowState.Unchanged;");
                    writer.WriteLine("                        }");
                    writer.WriteLine("                    }");
                    writer.WriteLine("                    else if ( _ORMDataState == DataRowState.Modified)");
                    writer.WriteLine("                    {");
                    writer.WriteLine("                        if ( _ORMEngine.Update(this) > 0)");
                    writer.WriteLine("                        {");
                    writer.WriteLine("                            _ORMDataState = DataRowState.Unchanged;");
                    writer.WriteLine("                        }");
                    writer.WriteLine("                    }");
                    writer.WriteLine("                }");
                    writer.WriteLine("            }");
                    writer.WriteLine("");
                }

                //writer.WriteLine("    public override string ToString(){ return base.ToString();}");

                writer.WriteLine("    }//public class TempClass");
            }
            writer.WriteLine("");
            writer.WriteLine("}//public class Helper");


            return writer.ToString();
        }

        private class SortPriorityComparer : System.Collections.IComparer
        {
            #region IComparer 成员

            public int Compare(object x, object y)
            {
                ORMPropertyInfo p1 = (ORMPropertyInfo)x;
                ORMPropertyInfo p2 = (ORMPropertyInfo)y;
                return p1.SortPriority - p2.SortPriority;
            }

            #endregion
        }

        public static string GenerateEntryClassCode(ORMProjectInfo project, ORMTypeInfo type)
        {
            StringWriter writer = new StringWriter();
            writer.WriteLine("[ORMType(\"" + type.TableName + "\")]");
            writer.WriteLine("public class Class" + type.TableName);
            writer.WriteLine("{");
            foreach (ORMPropertyInfo property in type.Properties)
            {
                string fieldName = property.RuntimeDBFieldName;
                if (Util.HasContent(fieldName) == false)
                {
                    continue;
                }
                writer.WriteLine();
                writer.Write("    private " + ToTypeNameCode(property.PropertyType, true) + " _" + property.Name + " = ");
                Dictionary<Type, string> defaultValues = new Dictionary<Type, string>();
                defaultValues[typeof(byte)] = "(byte)0";
                defaultValues[typeof(sbyte)] = "(sbyte)0";
                defaultValues[typeof(char)] = "'\0'";
                defaultValues[typeof(short)] = "(short)0";
                defaultValues[typeof(ushort)] = "(ushort)0";
                defaultValues[typeof(int)] = "0";
                defaultValues[typeof(uint)] = "0";
                defaultValues[typeof(long)] = "0";
                defaultValues[typeof(ulong)] = "0";
                defaultValues[typeof(float)] = "(float)0";
                defaultValues[typeof(double)] = "(double)0";
                defaultValues[typeof(decimal)] = "(decimal)0";
                defaultValues[typeof(string)] = "null";
                defaultValues[typeof(DateTime)] = "DateTime.Now";
                defaultValues[typeof(bool)] = "false";
                if (defaultValues.ContainsKey(property.PropertyType))
                {
                    writer.Write(defaultValues[property.PropertyType]);
                }
                else if (property.PropertyType.IsValueType)
                {
                    writer.Write("new " + ToTypeNameCode(property.PropertyType, true));
                }
                else
                {
                    writer.Write("null");
                }
                writer.Write(" ;");
                writer.WriteLine();
                if (property.Ignore)
                {
                    writer.Write("    [ORMIgnoreAttribute()]");
                }
                else
                {
                    writer.Write("    [ORMFieldAttribute(");
                    if (Util.HasContent(property.DBFieldName))
                    {
                        writer.Write(ToStringValueCode(property.DBFieldName));
                    }
                    if (Util.HasContent(property.Format))
                    {
                        writer.Write(",Format = " + ToStringValueCode(property.Format));
                    }
                    if (Util.HasContent(property.ComparabilityDBFieldName))
                    {
                        writer.Write(",ComparabilityFieldName=" + ToStringValueCode(property.ComparabilityDBFieldName));
                    }
                    if (Util.HasContent(property.ComparabilityDBFieldName2))
                    {
                        writer.Write(",ComparabilityFieldName2=" + ToStringValueCode(property.ComparabilityDBFieldName2));
                    }
                    if (property.ExtCondition != ORMBooleanValue.Default)
                    {
                        writer.Write(",ExtCondition=ORMBooleanValue." + property.ExtCondition.ToString());
                    }
                    if (property.DBValueType != ORMDBValueType.Default)
                    {
                        writer.Write(",DBValueType=ORMDBValueType." + property.DBValueType.ToString());
                    }
                    writer.Write(")]");
                    writer.WriteLine();
                    if (property.KeyField)
                    {
                        writer.WriteLine("    [ORMKeyFieldAttribute()]");
                    }
                    if (property.NewValueGenerate != null && property.NewValueGenerate.Style != ORMNewValueGenerateStyle.None)
                    {
                        writer.Write("    [ORMNewValueGenerateAttribute( ORMNewValueGenerateStyle." + property.NewValueGenerate.Style.ToString());
                        if (Util.HasContent(property.NewValueGenerate.Format))
                        {
                            writer.Write(", Format = " + ToStringValueCode(property.NewValueGenerate.Format));
                        }
                        writer.Write(")]");
                        writer.WriteLine();
                    }
                    if (property.Relation != null && property.Relation.Style != ORMRelationStyle.None)
                    {
                        writer.Write("    [ORMRelationAttribute(");
                        if (property.Relation.Style != ORMRelationStyle.Auto)
                        {
                            writer.Write("ORMRelationStyle." + property.Relation.Style.ToString());
                        }
                        if (Util.HasContent(property.Relation.ParentPropertyName))
                        {
                            writer.Write(",ParentFieldName=" + ToStringValueCode(property.Relation.ParentPropertyName));
                        }
                        if (Util.HasContent(property.Relation.ChildPropertyName))
                        {
                            writer.Write(",ChildFieldName=" + ToStringValueCode(property.Relation.ChildPropertyName));
                        }
                        if (property.Relation.LogReference == false)
                        {
                            writer.Write(",LogReference=false");
                        }
                        if (property.Relation.UniteDeleteForDelete)
                        {
                            writer.Write(",UniteDeleteForDelete=true");
                        }
                        if (property.Relation.UniteDeleteForUpdate)
                        {
                            writer.Write(",UniteDeleteForUpdate=true");
                        }
                        writer.Write(")]");
                        writer.WriteLine();
                    }
                    if (property.SortStyle != ORMSortStyle.None)
                    {
                        writer.Write("    [ORMSortAttribute( ORMSortStyle." + property.SortStyle.ToString());
                        if (property.SortPriority != 0)
                        {
                            writer.Write(",Priority=" + property.SortPriority);
                        }
                        writer.Write(")]");
                        writer.WriteLine();
                    }
                    if (property.DelayLoad)
                    {
                        writer.WriteLine("    [ORMDelayAttribute()]");
                    }
                    if (Util.HasContent(property.CommandText))
                    {
                        writer.WriteLine("    [ORMCommandTextAttribute(" + ToStringValueCode(property.CommandText) + ")]");
                    }
                    if (Util.HasContent(property.CopyThisReferenceTarget))
                    {
                        writer.WriteLine("    [ORMCopyThisReferenceAttribute(" + ToStringValueCode(property.CopyThisReferenceTarget) + ")]");
                    }
                    if (property.DBReadonly)
                    {
                        writer.WriteLine("    [ORMReadonlyAttribute()]");
                    }
                    if (property.ParentReference == ORMBooleanValue.True)
                    {
                        writer.WriteLine("    [ORMParentReferenceAttribute( )]");
                    }
                }//else
                writer.WriteLine("    public virtual " + ToTypeNameCode(property.PropertyType, true) + " " + property.Name);
                writer.WriteLine("    {");
                writer.WriteLine("         get");
                writer.WriteLine("         {");
                writer.WriteLine("              return _" + property.Name + " ;");
                writer.WriteLine("         }");
                writer.WriteLine("         set");
                writer.WriteLine("         {");
                writer.WriteLine("              _" + property.Name + " = value;");
                writer.WriteLine("         }");
                writer.WriteLine("    }");
                writer.WriteLine();
            }//foreach
            writer.WriteLine("}//class yfyuan");
            return writer.ToString();
        }
    }
}
